#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <unistd.h>

// Debug Server: bluepill.cs.umd.edu:9999
// Server: 128.8.126.92:6313
// Put the two's complement of the number in the string that is passed in.
char *get_complement (int num, char *str) {
    int i;
    str[8] = 0;
    
    //printf("Number: %d\n", num);
    //printf("Bits:");
    //for (i = 0; i < 8; ++i) {
    //    if (num & (1 << (7-i))) {
    //        printf("%s", "1");
    //    } else {
    //        printf("%s", "0");
    //    }
    //}
    //printf("\n");

    //printf("Flipped:");
    for (i = 0; i < 8; ++i) {
        if (num & (1 << (7-i))) {
            str[i] = '0';
        } else {
            str[i] = '1';
        }
    }
    //printf("%s\n", str);
   
    //printf("Plus one:");
    for (i = 7; i >= 0; --i) {
        if (str[i] == '0') {
            str[i] = '1';
            break;
        } else {
            str[i] = '0';
        }
    }
    //printf("%s\n", str);

    return str;
}
int main() {
    //char* hostname = "bluepill.cs.umd.edu";
    //char* serv_ip = getIPFromHostname(hostname, strlen(hostname))
    char *serv_ip = "128.8.126.92";
    short port = 6313; //short port = 9999;
    int random, ret, split_index, i; // random number
    time_t seconds;
    char *username = "lvalenta";
    char *reverse_username = "atnelavl";
    int BUFSIZE = strlen(username) + 5; // #(chars in username) + #('#' -- 1) + #(chars in twos number -- max 3) + (null character -- 1)
    char send_buffer[BUFSIZE]; // The string we send to the server: 'username#number'
    char recv_buffer[30]; // Not sure exactly how big the response message will be...
    char tc_buffer[9]; // The two's complement is returned as an 8-character string.
    struct sockaddr_in serv_addr; // server address

    // Generate number in range [-127,127]
    time(&seconds);
    srand((unsigned int) seconds);
    random= rand() % 255 - 127; 

    // Construct our string to send to the server
    sprintf(send_buffer, "%s#%d", username, random);
    //printf("Send_buffer: %s\n", send_buffer);

    // Construct our server's address
    memset(&serv_addr, 0, sizeof(serv_addr)); // Set all memory values to zero
    serv_addr.sin_family = AF_INET; // IPv4 address family
    serv_addr.sin_port = htons(port); // Change the port to network byte order
    ret = inet_pton(AF_INET, serv_ip, &serv_addr.sin_addr); // Convert address
    if (ret == 0) {
        printf("inet_pton() invalid address string");
        exit(1);
    } else if (ret < 0) {
        printf("inet_pton() failed");
        exit(1);
    }

    // Open a socket
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        printf("socket() failed");
        exit(1);
    }

    // Send message to server
    if (sendto(sockfd, send_buffer, strlen(send_buffer), 0, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) < 0) {
        printf("sendto() failed");
        exit(1);
    }
    int recvlen = recvfrom(sockfd, recv_buffer, 30, 0, 0, 0); // Can recieve additional info from server in last two paramters
    if (recvlen > 0) {
        recv_buffer[recvlen] = 0;
        //printf("Recv_buffer: %s\n", recv_buffer);
    } else {
        printf("recvfrom() failed");
        exit(1);
    }
    close(sockfd);
    
    // Find the index of the '#' string delimiter
    split_index = -1;
    for (i = 0; i < strlen(recv_buffer); ++i) {
        if (recv_buffer[i] == '#') {
            split_index = i;
            break;
        }
    }
    if (split_index == -1) {
        printf("parse failed");
        exit(1);
    }

    get_complement(random, tc_buffer);
    if (strncmp(reverse_username, recv_buffer, strlen(reverse_username)) != 0) {
        // Username failed
        // USERNAME:<u> $ INT:<i> $ RESULT:<outcome> $ REASON:<r>
        printf("USERNAME:%s $ INT:%d RESULT:failure $ REASON:username\n", username, random);
    } else if (strncmp(tc_buffer, recv_buffer+split_index+1, 8) != 0) {
        printf("USERNAME:%s $ INT:%d RESULT:failure $ REASON:complement\n", username, random);
    } else {
        printf("USERNAME:%s $ INT:%d RESULT:success\n", username, random);
    }

    return 0;
}
